home *** CD-ROM | disk | FTP | other *** search
/ Speccy ClassiX 1998 / Speccy ClassiX 98.iso / amiga_system / the_aminet / dev / gcc / ixemulsrc.lha / ixemul-41.4 / library / convert_dir.c < prev    next >
C/C++ Source or Header  |  1995-05-28  |  6KB  |  202 lines

  1. /*
  2.  *  This file is part of ixemul.library for the Amiga.
  3.  *  Copyright (C) 1991, 1992  Markus M. Wild
  4.  *  Portions Copyright (C) 1994 Rafael W. Luebbert
  5.  *
  6.  *  This library is free software; you can redistribute it and/or
  7.  *  modify it under the terms of the GNU Library General Public
  8.  *  License as published by the Free Software Foundation; either
  9.  *  version 2 of the License, or (at your option) any later version.
  10.  *
  11.  *  This library is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  *  Library General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU Library General Public
  17.  *  License along with this library; if not, write to the Free
  18.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  *
  20.  *  $Id: convert_dir.c,v 1.4 1994/06/19 15:09:22 rluebbert Exp $
  21.  *
  22.  *  $Log: convert_dir.c,v $
  23.  *  Revision 1.4  1994/06/19  15:09:22  rluebbert
  24.  *  *** empty log message ***
  25.  *
  26.  *  Revision 1.2  1992/07/28  00:42:36  mwild
  27.  *  fix signals, fix memory leak, fix possible never unlocked lock
  28.  *
  29.  *  Revision 1.1  1992/05/14  19:55:40  mwild
  30.  *  Initial revision
  31.  *
  32.  */
  33.  
  34. #define KERNEL
  35. #include "ixemul.h"
  36. #include "kprintf.h"
  37.  
  38. /* don't need to use the async port, no more than 1 task will be in here
  39.  * at a time and use our packet */
  40. #define __srwport (u.u_sync_mp)
  41.  
  42. extern int __mread (), __mclose ();
  43.  
  44. extern void *kmalloc (size_t), *krealloc (void *, size_t);
  45.  
  46. #if __GNUC__ != 2
  47. #define alloca __builtin_alloca
  48. #endif
  49.  
  50. #define BUFINCR    512
  51.  
  52. /* we're writing records that look like this to the `file' */
  53. struct file_dir {
  54.   long    fd_key;
  55.   long    fd_namelen;    /* padded to even size, thus perhaps zero padded */
  56.   char    fd_name[0];    /* fd_namelen bytes of filename */
  57. };
  58.  
  59. /*
  60.  * Convert a directory into a DTYPE_MEM file.
  61.  *
  62.  * NOTE: function assumes:
  63.  *     o f is allocated and locked, it's packet is initialized
  64.  *       o name is an existing directory (S_IFDIR from a previous stat)
  65.  *     o signals are blocked (important! convert_dir() doesn't block them!)
  66.  */
  67.  
  68. int
  69. convert_dir (struct file *f, char *name, int omask)
  70. {
  71.   BPTR lock;
  72.   u_char *buf, *bp, *bend;
  73.   int  buf_size;
  74.   struct FileInfoBlock *fib;
  75.   struct file_dir *fd;
  76.   int len, res, err, rc0;
  77.  
  78.   fib = alloca (sizeof (*fib) + 2);
  79.   fib = LONG_ALIGN (fib);
  80.   
  81.   res = 0;
  82.   if ((lock = __lock (name, ACCESS_READ)) > 0)
  83.     {
  84.       buf = kmalloc (BUFINCR);
  85.       buf_size = BUFINCR;
  86.       bp = buf;
  87.       bend = buf + buf_size;
  88.  
  89.       /* make sure we got that memory */
  90.       if (! buf)
  91.         {
  92.           err = ENOMEM;
  93.           res = -1;
  94.           goto do_return;
  95.         }
  96.       
  97.       rc0 = Examine (lock, fib);
  98.  
  99.       /* put two dummy entries here.. some BSD code relies on the fact that
  100.        * it can safely skip the first two `.' and `..' entries ;-)) */
  101.       fd = (struct file_dir *) bp;
  102.       fd->fd_key = 1;
  103.       fd->fd_namelen = 2;
  104.       fd->fd_name[0] = '.'; fd->fd_name[1] = 0;
  105.       bp += fd->fd_namelen + sizeof (struct file_dir);
  106.       fd = (struct file_dir *) bp;
  107.       fd->fd_key = 2;
  108.       fd->fd_namelen = 2;
  109.       fd->fd_name[0] = '.'; fd->fd_name[1] = '.';
  110.       bp += fd->fd_namelen + sizeof (struct file_dir);
  111.       
  112.       /* don't include the dir-information into the file, *ix doesn't either. */
  113.       if (rc0 == -1)
  114.     for (;;)
  115.       {
  116.         /* allow for a clean abort out of a very long directory scan */
  117.         if (u.p_sig & ~omask)
  118.           {
  119.         /* if a signal is pending that was not blocked before entry to
  120.          * open(), break here and return with EINTR */
  121.         res = -1;
  122.         err = EINTR;
  123.         kfree (buf);
  124.         goto do_return;
  125.           }
  126.  
  127.         rc0 = ExNext (lock, fib);
  128.  
  129.             if (rc0 != -1) break;
  130.  
  131.             len = strlen (fib->fib_FileName);
  132.  
  133.             if ((bp + (len + 2 + sizeof (struct file_dir))) >= bend)
  134.           {
  135.             u_char *tmp;
  136.  
  137.  
  138.             tmp = krealloc (buf, buf_size + BUFINCR);
  139.             if (! tmp)
  140.           {
  141.             ix_panic ("ixemul.library: out of memory!");
  142.             res = -1;
  143.             kfree (buf);
  144.             err = ENOMEM;
  145.             goto do_return;
  146.           }
  147.  
  148.             buf_size += BUFINCR;
  149.             bp = tmp + (bp-buf);
  150.             buf = tmp; 
  151.         bend = tmp + buf_size;
  152.           }
  153.  
  154.         fd = (struct file_dir *) bp;
  155.             fd->fd_key = fib->fib_DiskKey;
  156.             fd->fd_namelen = len;
  157.             /* watch out for mc68000: don't let bp ever get odd ! */
  158.             if (fd->fd_namelen & 1) 
  159.           /* in that case zero pad the name */
  160.           fd->fd_name[fd->fd_namelen++] = 0;
  161.  
  162.         bcopy (fib->fib_FileName, fd->fd_name, len);
  163.         bp += fd->fd_namelen + sizeof (struct file_dir);
  164. #ifdef DEBUG
  165.         if (bp >= bend || & fd->fd_name[len] >= bend)
  166.           {
  167.               KPRINTF (("cd: OVERFLOW! bp = $%lx, bend = $%lx, len = $%lx, &fd->fd_name[len] = $%lx\n",
  168.               bp, bend, len, & fd->fd_name[len]));
  169.           }
  170. #endif
  171.       }
  172.       
  173.       /* fine.. fill out the memory file object */
  174.       f->f_type        = DTYPE_MEM;
  175.       f->f_mf.mf_offset = 0;
  176.       f->f_mf.mf_buffer = buf;
  177.       f->f_read        = __mread;
  178.       f->f_close    = __mclose;
  179.       f->f_ioctl    = 0;
  180.       f->f_select    = 0;
  181.       f->f_stb.st_size    = bp-buf;
  182.       /* NOTE: the rest of the stb should be ok from the previous stat() in
  183.        *       open() */
  184.     }
  185.   else
  186.     {
  187.       errno = ENOENT;
  188.       KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  189.       return -1;
  190.     }
  191.  
  192.   /* NOTE: granted, this is a bit spaghetti here.. the else above guarantees that
  193.            we won't unlock a lock we never got. So it's safe to unconditionally
  194.            unlock at the end. */
  195.  
  196. do_return:
  197.   __unlock (lock);
  198.   errno = err;
  199.   KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  200.   return res;
  201. }
  202.